package com.atguigu.auth.service.impl;

import com.atguigu.auth.service.SysRoleMenuService;
import com.atguigu.auth.service.SysRoleService;
import com.atguigu.auth.utils.MenuHelper;
import com.atguigu.common.config.exception.GuiguException;
import com.atguigu.model.system.SysMenu;
import com.atguigu.auth.mapper.SysMenuMapper;
import com.atguigu.auth.service.SysMenuService;
import com.atguigu.model.system.SysRoleMenu;
import com.atguigu.vo.system.AssginMenuVo;
import com.atguigu.vo.system.MetaVo;
import com.atguigu.vo.system.RouterVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.api.R;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 菜单表 服务实现类
 * </p>
 *
 * @author atguigu
 * @since 2023-02-02
 */
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService {

    @Autowired
    private SysRoleMenuService sysRoleMenuService;

    @Autowired
    private SysRoleService sysRoleService;

    @Autowired
    private SysMenuService sysMenuService;
    //菜单列表接口
    @Override
    public List<SysMenu> findNodes() {

        //1 查询所有菜单数据
        List<SysMenu> sysMenuList = baseMapper.selectList(null);

        //2 构建树形结构
//        {
//            第一层
//            children:[
//            {
//                第二层
//                        ....
//            }
//            ]
//        }
        List<SysMenu> resultList = MenuHelper.buildTree(sysMenuList);
        return resultList;
    }

    //删除菜单
    @Override
    public void removeMenuById(Long id) {
        //判断当前菜单是否有下一层菜单
        LambdaQueryWrapper<SysMenu> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysMenu::getParentId,id);
        Integer count = baseMapper.selectCount(wrapper);
        if(count > 0) {
            throw new GuiguException(201,"菜单不能删除");
        }
        baseMapper.deleteById(id);
    }

    //查询所有菜单和角色分配的菜单
    @Override
    public List<SysMenu> findMenuByRoleId(Long roleId) {
        //1 查询所有菜单- 添加条件 status=1
        LambdaQueryWrapper<SysMenu> wrapperSysMenu = new LambdaQueryWrapper<>();
        wrapperSysMenu.eq(SysMenu::getStatus,1);
        List<SysMenu> allSysMenuList = baseMapper.selectList(wrapperSysMenu);

        //2 根据角色id roleId查询 角色菜单关系表里面 角色id对应所有的菜单id
        LambdaQueryWrapper<SysRoleMenu> wrapperSysRoleMenu = new LambdaQueryWrapper<>();
        wrapperSysRoleMenu.eq(SysRoleMenu::getRoleId,roleId);
        List<SysRoleMenu> sysRoleMenuList = sysRoleMenuService.list(wrapperSysRoleMenu);

        //3 根据获取菜单id，获取对应菜单对象
        List<Long> menuIdList = sysRoleMenuList.stream().map(c -> c.getMenuId()).collect(Collectors.toList());

        //3.1 拿着菜单id 和所有菜单集合里面id进行比较，如果相同封装
        allSysMenuList.stream().forEach(item -> {
            if(menuIdList.contains(item.getId())) {
                item.setSelect(true);
            } else {
                item.setSelect(false);
            }
        });

        //4 返回规定树形显示格式菜单列表
        List<SysMenu> sysMenuList = MenuHelper.buildTree(allSysMenuList);
        return sysMenuList;
    }

    //为角色分配菜单
    @Override
    public void doAssign(AssginMenuVo assginMenuVo) {
        //1 根据角色id 删除菜单角色表 分配数据
        LambdaQueryWrapper<SysRoleMenu> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysRoleMenu::getRoleId,assginMenuVo.getRoleId());
        sysRoleMenuService.remove(wrapper);

        //2 从参数里面获取角色新分配菜单id列表，
        // 进行遍历，把每个id数据添加菜单角色表
        List<Long> menuIdList = assginMenuVo.getMenuIdList();
        for(Long menuId:menuIdList) {
            if(StringUtils.isEmpty(menuId)) {
                continue;
            }
            SysRoleMenu sysRoleMenu = new SysRoleMenu();
            sysRoleMenu.setMenuId(menuId);
            sysRoleMenu.setRoleId(assginMenuVo.getRoleId());
            sysRoleMenuService.save(sysRoleMenu);
        }
    }

    /**
     * 根据用户的id，返回前端的框架中共需要的。
     * @param userId
     * @return
     */
    @Override
    public List<RouterVo> findMenuByUserId(Long userId) {
        List<SysMenu> MenuList= null;
       //1.根据用户的id，判断用户的身份，是不是管理员。
       List<Long> roleIds = sysRoleService.findRoleIdByUserId(userId);
       //管理员
       if(roleIds.contains(1L)){
           //是管理员的话，就是可以查看所有的菜单权限
           MenuList = sysMenuService.list(null);
       }
       //不是管理员，需要根据角色去得到相应的菜单。
       else{
           MenuList = sysMenuService.findListByUserId(userId);
       }
        //构建树形结构
        List<SysMenu> sysMenuList = MenuHelper.buildTree(MenuList);
       //将树形结构修改为前端菜单的结构。
        List<RouterVo> routerVoList = this.buildMenus(sysMenuList);
        return routerVoList;
    }

    /**
     * 根据用户id，查找相应的菜单
     * @param sysMenuList
     * @return
     */
    private List<RouterVo> buildMenus(List<SysMenu> sysMenuList) {
        List<RouterVo> routerVoList = new LinkedList<RouterVo>();
        for (SysMenu sysMenu : sysMenuList) {
            RouterVo routerVo = new RouterVo();
            routerVo.setHidden(false);
            routerVo.setAlwaysShow(false);
            routerVo.setPath(getRouterPath(sysMenu));
            routerVo.setComponent(sysMenu.getComponent());
            MetaVo metaVo = new MetaVo();
            metaVo.setTitle(sysMenu.getName());
            metaVo.setIcon(sysMenu.getIcon());
            routerVo.setMeta(metaVo);
            //需要对children的数据进行另外的处理。
            List<SysMenu> children = sysMenu.getChildren();
            //如果当前是菜单，需将按钮对应的路由加载出来，如“角色授权”按钮对应的路由在
            //在“系统管理”下面。
            if(sysMenu.getType().intValue() ==1 ){
                //获取菜单
                List<SysMenu> hiddenMenuList = children.stream()
                        .filter(item -> !StringUtils.isEmpty(item.getComponent()))
                        .collect(Collectors.toList());
                for (SysMenu menu : hiddenMenuList) {
                    RouterVo  hiddenMenu  = new RouterVo();
                    hiddenMenu.setHidden(true);
                    hiddenMenu.setAlwaysShow(false);
                    hiddenMenu.setPath(getRouterPath(menu));
                    hiddenMenu.setMeta(new MetaVo(menu.getName(),menu.getIcon()));
                    hiddenMenu.setComponent(menu.getComponent());
                    routerVoList.add(hiddenMenu);
                }

            }else{
                if(!CollectionUtils.isEmpty(children)){
                    if(children.size() > 0){
                        routerVo.setAlwaysShow(true);
                    }
                    routerVo.setChildren(buildMenus(children));
                }
            }
            routerVoList.add(routerVo);
        }
        return routerVoList;
    }
    /**
     *他的地址是有多部份组成的，
     * @param sysMenu
     * @return
     */
    private String getRouterPath(SysMenu sysMenu) {
        String routerPath = "/"+sysMenu.getPath();
        if(sysMenu.getParentId().intValue() != 0){
            routerPath = sysMenu.getPath();
        }
        return routerPath;
    }

    @Override
    public List<String> findPermsByUserId(Long userId) {
        List<String> permsList = baseMapper.findPermsByUserId(userId);
        return permsList;
    }

    /**
     * 根据用户id，查找相关的菜单集合
     * @param userId
     * @return
     */
    @Override
    public List<SysMenu> findListByUserId(Long userId) {
        List<SysMenu> sysMenuList = baseMapper.findListByUserId(userId);
        return sysMenuList;
    }
}
